package middleware

import (
	"fmt"
	"net/http"
	"time"

	"gitee.com/dreamwithouttrace/websocket-module/core"
	"github.com/go-redis/redis"
	"gorm.io/gorm"
)

// Middleware 中间件接口
type Middleware interface {
	Process(w http.ResponseWriter, r *http.Request) (core.User, error)
}

// AuthMiddleware 认证中间件
type AuthMiddleware struct {
	redis     *redis.Client                                      // Redis客户端接口
	db        *gorm.DB                                           // 数据库接口
	queryFunc func(db *gorm.DB, token string) (core.User, error) // 自定义查询函数
}

// NewAuthMiddleware 创建新的认证中间件
func NewAuthMiddleware(redis *redis.Client, db *gorm.DB, queryFunc func(db *gorm.DB, token string) (core.User, error)) *AuthMiddleware {
	return &AuthMiddleware{
		redis:     redis,
		db:        db,
		queryFunc: queryFunc,
	}
}

// Process 处理认证
func (m *AuthMiddleware) Process(config *core.Config, r *http.Request) (core.User, error) {
	// 获取访问令牌
	accessToken := r.URL.Query().Get(config.TokenName)
	if accessToken == "" {
		return nil, &AuthError{Message: "缺少访问令牌"}
	}

	// 检查Redis中的令牌
	if !m.checkTokenInRedis(accessToken) {
		return nil, &AuthError{Message: "授权失败"}
	}

	// 从数据库获取用户信息
	user, err := m.getUserFromDB(accessToken)
	if err != nil {
		return nil, &AuthError{Message: "用户不存在"}
	}

	// 检查用户状态
	if user.GetDisabledEndTime() > time.Now().Unix() {
		return nil, &AuthError{Message: "用户已被禁用"}
	}

	return user, nil
}

// checkTokenInRedis 检查Redis中的令牌
func (m *AuthMiddleware) checkTokenInRedis(token string) bool {
	// 这里需要根据具体的Redis实现来检查令牌
	// 示例实现：
	exists, err := m.redis.Exists(token).Result()
	if err != nil {
		return false
	}
	return exists == 1
}

// getUserFromDB 从数据库获取用户信息
func (m *AuthMiddleware) getUserFromDB(token string) (core.User, error) {
	// 如果提供了自定义查询函数，使用它
	if m.queryFunc != nil {
		return m.queryFunc(m.db, token)
	}

	// 如果没有提供查询函数，返回错误
	return nil, fmt.Errorf("no query function provided")
}

// TestClientMiddleware 测试客户端中间件
type TestClientMiddleware struct {
	db        *gorm.DB                                            // 数据库接口
	queryFunc func(db *gorm.DB, offset string) (core.User, error) // 自定义查询函数
}

// NewTestClientMiddleware 创建新的测试客户端中间件
func NewTestClientMiddleware(db *gorm.DB, queryFunc func(db *gorm.DB, offset string) (core.User, error)) *TestClientMiddleware {
	return &TestClientMiddleware{
		db:        db,
		queryFunc: queryFunc,
	}
}

// Process 处理测试客户端认证
func (m *TestClientMiddleware) Process(config *core.Config, r *http.Request) (core.User, error) {
	// 获取偏移量
	offset := r.URL.Query().Get(config.TokenName)
	if offset == "" {
		offset = "0"
	}

	// 根据偏移量获取用户
	user, err := m.getUserByOffset(offset)
	if err != nil {
		return nil, &AuthError{Message: "获取测试用户失败"}
	}

	// 检查用户状态
	if user.GetDisabledEndTime() > time.Now().Unix() {
		return nil, &AuthError{Message: "用户已被禁用"}
	}

	return user, nil
}

// getUserByOffset 根据偏移量获取用户
func (m *TestClientMiddleware) getUserByOffset(offset string) (core.User, error) {
	// 如果提供了自定义查询函数，使用它
	if m.queryFunc != nil {
		return m.queryFunc(m.db, offset)
	}

	// 如果没有提供查询函数，返回错误
	return nil, fmt.Errorf("no query function provided")
}

// RateLimitMiddleware 限流中间件
type RateLimitMiddleware struct {
	redis  interface{}   // Redis客户端接口
	limit  int           // 限制次数
	window time.Duration // 时间窗口
}

// NewRateLimitMiddleware 创建新的限流中间件
func NewRateLimitMiddleware(redis interface{}, limit int, window time.Duration) *RateLimitMiddleware {
	return &RateLimitMiddleware{
		redis:  redis,
		limit:  limit,
		window: window,
	}
}

// Process 处理限流
func (m *RateLimitMiddleware) Process(w http.ResponseWriter, r *http.Request) (core.User, error) {
	// 获取客户端IP
	clientIP := m.getClientIP(r)

	// 检查限流
	if !m.checkRateLimit(clientIP) {
		return nil, &RateLimitError{Message: "请求过于频繁"}
	}

	// 这里应该调用下一个中间件或处理器
	// 为了简化，这里返回nil
	return nil, nil
}

// getClientIP 获取客户端IP
func (m *RateLimitMiddleware) getClientIP(r *http.Request) string {
	// 获取X-Forwarded-For头
	if xff := r.Header.Get("X-Forwarded-For"); xff != "" {
		return xff
	}

	// 获取X-Real-IP头
	if xri := r.Header.Get("X-Real-IP"); xri != "" {
		return xri
	}

	// 获取RemoteAddr
	return r.RemoteAddr
}

// checkRateLimit 检查限流
func (m *RateLimitMiddleware) checkRateLimit(clientIP string) bool {
	// 这里需要根据具体的Redis实现来检查限流
	// 示例实现：
	// key := "rate_limit:" + clientIP
	// count, err := m.redis.Get(key).Int()
	// if err != nil && err != redis.Nil {
	//     return false
	// }
	// if count >= m.limit {
	//     return false
	// }
	// m.redis.Incr(key)
	// m.redis.Expire(key, m.window)
	return true
}

// AuthError 认证错误
type AuthError struct {
	Message string
}

func (e *AuthError) Error() string {
	return e.Message
}

// RateLimitError 限流错误
type RateLimitError struct {
	Message string
}

func (e *RateLimitError) Error() string {
	return e.Message
}
